#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MAX_SIZE 1000
#define MAX_OPRATE 100 
#define SEP " "
#define STREND '\0'
//###############################重定向
#define  None_Redir -1
#define  Stdin_Redir 0
#define  Stdout_Redir 1
#define  Append_Redir 2


int redir_type=None_Redir;
char*filename=NULL;
//#############################
char* argv[MAX_OPRATE];
char pwd[1024];
char myenv[100];



const char*getAll(char*str)
{
 const char* ret=getenv(str);
  if(ret)return ret;
  else return "None";
}
const char*UserName()
{
 const char*hostname=getAll("USER");
  return hostname;
}
const char* CurrrentWorkspace()
{
 const  char*workspace=getAll("PWD");
  return workspace;
}
const char*Hostname()
{
 const char*name=getAll("HOSTNAME");
  return name;
}
char*Home()
{
  return getenv("HOME");
}
void findfile(char in[],int pos)
{
      while(in[pos]==' ')
      {
         ++pos;
      }
    filename=in+pos;
}
void CheckRedir(char in[])//重定向检查
{
  int pos=strlen(in)-1;
  redir_type=None_Redir;
  while(pos>=0)
  {
    if(in[pos]=='<')
    {
      redir_type=Stdin_Redir;//标准输入
      in[pos++]=STREND;//往后走
      findfile(in,pos);
      break;
    }
    else if(in[pos]=='>')
    {
      if(in[pos-1]=='>'){
        redir_type=Append_Redir;//追加
        in[pos-1]=STREND;
        findfile(in,pos);
        break;
      }
      else{
       redir_type=Stdout_Redir;//标准输出
       printf("输出重定向");
       in[pos++]=STREND;
       findfile(in,pos);
       break; 
      }
    }
    else{
      pos--;
    }
  }

}
int buildincmd()//判断是否为内建命令
{
    int ret=0;
    if(strcmp("cd",argv[0])==0)
    {
      ret=1;
      char*target=argv[1];
      if(!target)target=Home();
      chdir(target);
      char tmp[1024];
      getcwd(tmp,1024);//重新获取环境变量路径
      snprintf(pwd,MAX_SIZE,"PWD=%s",tmp);//打给pwd
      putenv(pwd);//重新输出环境变量路径
    }
    else if(strcmp("export",argv[0])==0)//导入环境变量
    {
      ret=1;
      if(argv[1])//putenv(argv[1]);//argv每次都会重新刷新 这样不行的
      {
        strcpy(myenv,argv[1]);//放进全局变量,子进程继承父进程代码数据
      }
      putenv(myenv);//导入
    }
    return ret;
}

int Interative(char out[],int size)//获取 
{
      printf("[%s@%s %s]$",UserName(),Hostname(),CurrrentWorkspace());
      fgets(out,size,stdin);
      out[strlen(out)-1]=0;//清除'\0'                                
      return (strlen(out));
}

void spilt(char*commandline){
  int i=0;
  CheckRedir(commandline);
  argv[i++]=strtok(commandline,SEP);//分隔字符串
  while(argv[i++] = strtok(NULL,SEP));
  if(strcmp(argv[0],"ls")==0)
  {
    argv[i-1]=(char*)"--color";//带彩色
    argv[i]=NULL;
  }
}
//执行
void excute(){  
  pid_t id=fork();
  umask(0);
  if(id==0)
  {
    int fd=-1;
    if(redir_type==Stdin_Redir)
    {
       fd=open(filename,O_RDONLY,0666);//输入
       if(!fd)perror("打开文件错误");
       dup2(fd,0);
    }
    else if(redir_type==Stdout_Redir)
    {
      printf("输出重定向\n");
      fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);//清空
       if(!fd)perror("打开文件错误");
      dup2(fd,1);
    }
    else if(redir_type==Append_Redir)//追加
    {
      fd=open(filename,O_WRONLY|O_CREAT|O_APPEND,0666);
       if(!fd)perror("打开文件错误");
      dup2(fd,1);
    }
    else
    {
      //nothing
    }
    execvp(argv[0],argv);
    exit(1);
  }
  pid_t rid=waitpid(id,NULL,0);
}

int main()
{
 while(1){
  char commandline[MAX_SIZE];
  
  int n=(Interative(commandline,MAX_SIZE));
  if(n==0)continue;
                        
  spilt(commandline);//分割字符
  
  n=buildincmd();
  if(n)continue;

  excute();
  }
  return 0;

}




